/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain (a) copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.sentry.ohos.core.util;

import io.sentry.ILogger;
import io.sentry.SentryLevel;
import io.sentry.ohos.core.IBuildInfoProvider;
import ohos.app.Context;
import ohos.bundle.IBundleManager;
import ohos.net.NetCapabilities;
import ohos.net.NetHandle;
import ohos.net.NetManager;

import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * This is ConnectivityChecker
 *
 * @since 2021-06-01
 */
@ApiStatus.Internal
public final class ConnectivityChecker {
    /**
     * This is Status
     *
     * @since 2021-06-01
     */
    public enum Status {
        /**
         * CONNECTED 连接的
         */
        CONNECTED,
        /**
         * NOT_CONNECTED 没有连接的
         */
        NOT_CONNECTED,
        /**
         * NO_PERMISSION 没有许可
         */
        NO_PERMISSION,
        /**
         * UNKNOWN 未知
         */
        UNKNOWN
    }

    private ConnectivityChecker() {
    }

    /**
     * Return the Connection status
     *
     * @param context Context
     * @param logger ILogger
     * @return the ConnectionStatus
     */
    public static @NotNull ConnectivityChecker.Status getConnectionStatus(
        final @NotNull Context context, final @NotNull ILogger logger) {
        final NetManager connectivityManager = NetManager.getInstance(context);

        if (connectivityManager == null) {
            return Status.UNKNOWN;
        }
        return getConnectionStatus(context, connectivityManager, logger);

        // getActiveNetworkInfo might return null if VPN doesn't specify its
        // underlying network

        // when min. API 24, use:
        // connectivityManager.registerDefaultNetworkCallback(...)
    }

    /**
     * Return the Connection status
     *
     * @param context the Context
     * @param connectivityManager the NetManager
     * @param logger the Logger
     * @return true if connected or no permission to check, false otherwise
     */
    @SuppressWarnings({"deprecation", "MissingPermission"})
    private static @NotNull ConnectivityChecker.Status getConnectionStatus(
        final @NotNull Context context,
        final @NotNull NetManager connectivityManager,
        final @NotNull ILogger logger) {
        if (context.verifyCallingPermission("ohos.permission.GET_NETWORK_INFO") != IBundleManager.PERMISSION_GRANTED) {
            logger.log(SentryLevel.INFO, "No permission (ACCESS_NETWORK_STATE) to check network status.");
            return Status.NO_PERMISSION;
        }

        NetHandle defaultNet = connectivityManager.getDefaultNet();
        if (defaultNet == null) {
            logger.log(SentryLevel.INFO, "NetworkInfo is null, there's no active network.");
            return Status.NOT_CONNECTED;
        }
        return Status.CONNECTED;
    }

    /**
     * Check the connection type of the active network
     *
     * @param context the Hap. context
     * @param logger the logger from options
     * @param buildInfoProvider the BuildInfoProvider provider
     * @return the connection type wifi, ethernet, cellular or null
     */

    public static @Nullable String getConnectionType(
        final @NotNull Context context,
        final @NotNull ILogger logger,
        final @NotNull IBuildInfoProvider buildInfoProvider) {
        final NetManager connectivityManager = NetManager.getInstance(context);
        if (connectivityManager == null) {
            return "";
        }
        if (context.verifyCallingPermission("ohos.permission.GET_NETWORK_INFO") != IBundleManager.PERMISSION_GRANTED) {
            logger.log(SentryLevel.INFO, "No permission (ACCESS_NETWORK_STATE) to check network status.");
            return "";
        }
        boolean isEthernet = false;
        boolean isWifi = false;
        boolean isCellular = false;
        NetHandle defaultNet = connectivityManager.getDefaultNet();
        NetCapabilities netCapabilities = connectivityManager.getNetCapabilities(defaultNet);
        isEthernet = netCapabilities.hasBearer(NetCapabilities.BEARER_ETHERNET);
        isWifi = netCapabilities.hasBearer(NetCapabilities.BEARER_WIFI);
        isCellular = netCapabilities.hasBearer(NetCapabilities.BEARER_CELLULAR);
        if (isEthernet) {
            return "ethernet";
        }
        if (isWifi) {
            return "wifi";
        }
        if (isCellular) {
            return "cellular";
        }
        return "";
    }
}
